﻿using gt.IdentityServer.Extensions;
using IdentityServer4.Models;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;

namespace gt.IdentityServer
{
    public class IdentityServerConfig
    {
        public static IEnumerable<ApiResource> GetApiResources(IConfiguration configuration)
        {
            var apiResources = new List<ApiResource>();
            foreach (var child in configuration.GetSection("IdentityServer:ApiResources").GetChildren())
            {
                var name = child.GetValue<string>("Name");
                var displayName = child.GetValue<string>("DisplayName");
                var scopes = child.GetSection("ApiScopes").Get<string[]>();
                var apiResource = new ApiResource(name, displayName);
                apiResource.Scopes = scopes;
                apiResources.Add(apiResource);

            }

            //更细粒度的resource:ApiScope

            return apiResources;
        }
        /*
         * identityserver4 4.x版本 need apiscopes
         * */
        public static IEnumerable<ApiScope> GetApiScopes(IConfiguration configuration)
        {
            var apiScopes = new List<ApiScope>();
            foreach (var child in configuration.GetSection("IdentityServer:ApiScopes").GetChildren())
            {
                var name = child.GetValue<string>("Name");
                var displayName = child.GetValue<string>("DisplayName");
                var claimTypes = child.GetSection("ClaimTypes").Get<string[]>();
                var scope = new ApiScope(name, displayName, claimTypes);
                apiScopes.Add(scope);
            }

            //更细粒度的resource:ApiScope

            return apiScopes;
        }

        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new IdentityResource[]
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),

                new AppUserIdentityResource()
            };
        }

        //note:path.combile 不适用docker
        public static X509Certificate2 GetCertificate(IConfiguration configuration)
        {
            var assembly = typeof(IdentityServerConfig).GetTypeInfo().Assembly;
            //程序集命名空间.资源文件所在文件夹名.资源文件名
            using (var stream = assembly.GetManifestResourceStream("gt.IdentityServer.Security.certificate.idsrv4.pfx"))
            {
                return new X509Certificate2(ReadStream(stream), configuration["IdentityServer:Certificates:Password"]);
            }
        }
        private static byte[] ReadStream(Stream input)
        {
            byte[] buffer = new byte[16 * 1024];
            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }
                return ms.ToArray();
            }
        }
        //todo oidc client identityresource get
        public static IEnumerable<Client> GetClients(IConfiguration configuration)
        {
            var clients = new List<Client>();
            foreach (var child in configuration.GetSection("IdentityServer:Clients").GetChildren())
            {
                clients.Add(new Client
                {
                    ClientId = child["ClientId"],
                    ClientName = child["ClientName"],
                    
                    AllowedGrantTypes = child.GetSection("AllowedGrantTypes").GetChildren().Select(c => c.Value).ToArray(),
                    RequireConsent = bool.Parse(child["RequireConsent"] ?? "false"),
                    ClientSecrets = child.GetSection("ClientSecrets").GetChildren().Select(secret => new Secret(secret["Value"].Sha256())).ToArray(),
                    AllowedScopes = child.GetSection("AllowedScopes").GetChildren().Select(c => c.Value).ToArray(),
                    RedirectUris = child.GetSection("RedirectUris")?.GetChildren().Select(c => c.Value).ToArray(),
                    PostLogoutRedirectUris = child.GetSection("PostLogoutRedirectUris")?.GetChildren().Select(c => c.Value).ToArray(),
                    AllowOfflineAccess = true,
                    AlwaysIncludeUserClaimsInIdToken = true,
                    AlwaysSendClientClaims = false,
                    RequirePkce=false
                });
            }
            return clients;
        }
    }
}
